home *** CD-ROM | disk | FTP | other *** search
/ MacHack 1997 / MacHack 1997.toast / Hacks / Hacks ’95 / Venus / FractalMap.cc < prev    next >
C/C++ Source or Header  |  1995-06-23  |  5KB  |  128 lines

  1. // This may look like C code, but it is really -*- C++ -*-
  2. /*
  3.  ************************************************************************
  4.  *
  5.  *                           Generating Fractal Maps
  6.  *
  7.  * We use the following algorithm described in the "documentation" to
  8.  * program MARS (Tim Clarke, tjc1005@hermes.cam.ac.uk, posted in some "games"
  9.  * group)
  10.  *
  11.  * "This is a recursive subdivision, or plasma, fractal. You start of
  12.  * with a random height at (0,0) and therefore also at (256,0), (0,256),
  13.  * (256,256).  Call a routine that takes as input the size and position
  14.  * of a square, in the first case the entire map.
  15.  * This routine get the heights from the corners of the square it gets
  16.  * given.  Across each edge (if the map has not been written to at the
  17.  * point halfway along that edge), it takes the average of the heights of
  18.  * the 2 corners on that edge, applies some noise proportional to the
  19.  * length of the edge, and writes the result into the map at a position
  20.  * halfway along the edge. The center of the square is the average of the
  21.  * four corners+noise.
  22.  * The routine then calls itself recursively, splitting each square into
  23.  * four quadrants, calling itself for each quadrant until the length of
  24.  * the side is 2 pixels.
  25.  * This is probably old-hat to many people, but the map is made more
  26.  * realistic by blurring [applying some filter to it]
  27.  * The colors are done so that the sun is on the horizon to the East:
  28.  *     Color=A*[ w(u+1,v)-w(u,v) ]+B
  29.  * with A and B chosen so that the full range of the palette is used.
  30.  * The sky is a similar fractal but without the colour transformation"
  31.  * <EOQ>
  32.  *
  33.  * Again, one can achieve this effect by applying an appropriate filter.
  34.  * In principle, the filter for blurring and the filter for coloring
  35.  * (the latter looks like a simple gradient/edge enhancement filter)
  36.  * can be combined in a single one. 
  37.  *
  38.  * In the present program, we use an iterative rather than recursive
  39.  * procedure.
  40.  *
  41.  ************************************************************************
  42.  */
  43.  
  44. #include "std.h"
  45. #include "image.h"
  46. #include "myenv.h"
  47.                                     // Fractal "cloud"
  48. class FractalMap : public IMAGE
  49. {
  50.     void make_fractal_map(const int scale);
  51.     
  52. public:
  53.     FractalMap(const int dimension);
  54.     ~FractalMap(void)  {}
  55.     
  56.     void display(const char * title) const;
  57.     
  58. };
  59.  
  60.                                         // Construng a fractal "cloud"
  61. FractalMap::FractalMap(const int dimension) : IMAGE(dimension,dimension,8)
  62. {
  63.     (*this)(0,0) = 128;                    // Seed
  64.     
  65.     register int scale;
  66.     for(scale=dimension; scale>1; scale >>= 1)
  67.         make_fractal_map(scale);
  68. }
  69.  
  70.                                     // Get some noise with a dispersion 'scale'
  71.                                     // (which is assumed to be a power of 2)
  72.                                     // and average 0
  73.                                     // Say, if scale=2 return either 0 or 1
  74.                                     // if scale=128, return the random number
  75.                                     // within [-64,63]
  76.                                     // Note, that usually a couple of low-order
  77.                                     // bits of Random() are "less" random; therefore,
  78.                                     // we shift them out.
  79. static int get_noise(const int scale)
  80. {
  81.     return ((Random() >> 2) & (scale/2-1)) - scale/4;
  82. }
  83.  
  84.                                     // Make the fractal map at a specified scale
  85.                                     // Keep in mind "wrap-around" property of
  86.                                     // the map
  87. void FractalMap::make_fractal_map(const int scale)
  88. {
  89.     register int i, j;
  90.     for(i=0; i<q_nrows(); i += scale)
  91.        for(j=0; j<q_ncols(); j += scale)
  92.        {
  93.             int i_up = i+scale; if( i_up >= q_nrows() ) i_up-=q_nrows();
  94.             int j_up = j+scale; if( j_up >= q_ncols() ) j_up-=q_ncols();
  95.             int i_hp = i+scale/2; if( i_hp >= q_nrows() ) i_hp-=q_nrows();
  96.             int j_hp = j+scale/2; if( j_hp >= q_ncols() ) j_hp-=q_ncols();
  97.             int corner00 = (*this)(i,j);
  98.             int corner10 = (*this)(i_up,j);
  99.             int corner01 = (*this)(i,j_up);
  100.             int corner11 = (*this)(i_up,j_up);
  101.             //message("i %d, j%d, scale %d Corners %d %d %d %d",i,j,scale,corner00,corner01,corner10,corner11);
  102.             int mid30 = (*this)(i_hp,j) = (corner00+corner10)/2 + get_noise(scale);
  103.             int mid03 = (*this)(i,j_hp) = (corner00+corner01)/2 + get_noise(scale);
  104.             int mid31 = (*this)(i_hp,j_up) = (corner01+corner11)/2 + get_noise(scale);
  105.             int mid13 = (*this)(i_up,j_hp) = (corner10+corner11)/2 + get_noise(scale);
  106.             (*this)(i_hp,j_hp) = (mid30+mid03+mid31+mid13)/4 + get_noise(scale);
  107.        }
  108.        
  109. }
  110.  
  111.  
  112. void project_3D(const IMAGE& image, const char * title);
  113.  
  114. void main(void)
  115. {
  116.     Initialize_MAC();
  117.  
  118.     GetDateTime((unsigned long *)&qd.randSeed);
  119.     Random(); Random(); Random(); Random();                    // Just randomizing
  120.     
  121.     FractalMap map(256);
  122.     map.clip_to_intensity_range();
  123. //    map.invert();
  124. //    map.write_pgm("map.pgm");
  125.     project_3D(map,"map");    
  126. //    display_map(map,"map");    
  127. }
  128.